package com.opcode.costa.ui.splashscreen;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;

import com.opcode.costa.R;
import com.opcode.costa.ui.dashboard.leftmenu.LeftMenuActivity;
import com.opcode.costa.ui.dialogs.LoginPasswordDialogFragment;
import com.opcode.nebulamobil.base.activities.DialogShowerActivityBase;
import com.opcode.nebulamobil.base.activities.FragmentActivityBase;
import com.opcode.nebulamobil.base.components.ImageViewBase;
import com.opcode.nebulamobil.base.components.ListViewBase;
import com.opcode.nebulamobil.base.components.TextViewBase;
import com.opcode.nebulamobil.base.fragments.ResponsiveFragmentBase;
import com.opcode.nebulamobil.base.fragments.dialogfragments.RoundedProgressDialogBase;
import com.opcode.nebulamobil.base.fragments.dialogfragments.TwoButtonDialogFragmentBase;
import com.opcode.nebulamobil.base.interfaces.ConnectionListener;
import com.opcode.nebulamobil.base.interfaces.OnListViewBaseItemClickListener;
import com.opcode.nebulamobil.enums.TwoButtonDialogType;
import com.opcode.nebulamobil.information.ApplicationInfo;
import com.opcode.nebulamobil.information.dataforms.costadataforms.ConnectionStatus;
import com.opcode.nebulamobil.information.dataforms.costadataforms.ConnectionStatus.ConnectionStatusInfo;
import com.opcode.nebulamobil.information.dataforms.costadataforms.PersonalDataForm;
import com.opcode.nebulamobil.information.requests.costarequests.PersonalListReq;
import com.opcode.nebulamobil.information.responses.JSONResponse;
import com.opcode.nebulamobil.information.responses.costaresponses.PersonalListResp;
import com.opcode.nebulamobil.information.responses.costaresponses.UpdateResp;
import com.opcode.nebulamobil.utility.FileProcess;
import com.opcode.nebulamobil.utility.JsonConverter;
import com.opcode.nebulamobil.utility.UniqueIdCreator;

/**
 * Bu fragment içerisinde kullanıcı tarafından kullanıcı adı ve şifre bilgileri
 * alınır. Kullanıcı adı bilgisi listeden personel seçilerek elde edilecektir.
 * Alınan bu bilgiler sunucuda kontrol edildikten sonra,bilgiler doÛruysa
 * dashboard ekranına yönlendirme yapılır. Aksi halde hatalı giriş yaptınız
 * uyarısı verilir.
 * 
 * @author Okan ERDOĞAN 29/05/2014
 */
public class LoginFragment extends ResponsiveFragmentBase implements ConnectionListener{

	private View vi;

	/*
	 * Kullanıcı adı ve şifre bilgileri kontrol edildikten sonra aılacak olan
	 * DashBoardActivity'ye ilişkin intent nesnesinin referansıdır. Bu nesne
	 * referansı ile aktiviteler arasında geçiş yapılır. Aktiviteler arasında
	 * veri taşınması için de intent nesnesinin putExtra metodları
	 * kullanılabilir.
	 */
	private Intent intent;

	/*
	 * Personel ListView nesne referansı kullanıcılara personel listesini
	 * göstermek için kullanılacaktır. Bu listview'ın içerğini oluşturmak için
	 * personalInfoArray ve personalListAdapter nesnelerine de ihtiyaç
	 * duyacağız.
	 */
	private ListViewBase personalListview;

	/*
	 * Parametre olarak almış olduğu layout ve arraylist verilerine göre
	 * listView objesinin içeriğini düzenler.
	 */
	private PersonalListAdapter personalListAdapter;

	/*
	 * Cafede çalışan personel bilgisinin tutulduğu nesne referansıdır. Personel
	 * bilgisi sunucudan gönderilecektir. Bu bilgi uygulamanın her aılışında
	 * sorulabilir. Ya da bir değişiklik olması durumunda personel listesi
	 * güncellenir.
	 */
	private ArrayList<PersonalDataForm> personalInfoArray;

	private Handler myHandler = null;
	private Runnable myRunnable = null;
	
	private RoundedProgressDialogBase roundedProgressDialogBase;
	
	public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
		/*
		 * Bu bölmde fragment içerisinde kullanacağımız nesneler oluşturuluyor.
		 * View nesneleri layout dosyasından elde edilerek referansa
		 * bağlanıyorlar.
		 */
		this.vi = inflater.inflate(R.layout.login_fragment_layout, container,false);
		this.personalListview = (ListViewBase) this.vi.findViewById(R.id.personal_listview);

		myHandler = new Handler();

		/*
		 * Personel list view nesnesinden herhangi bir seçenek tıklandığı zaman
		 * aşağıdaki onItemClick metodu tetiklenir. onItemClick metodu
		 * içerisinde elde edilen personel bilgisi ve intent nesnesi parametre
		 * olarak kullanılarak PasswordDialog ekranı aılır.
		 */
		this.personalListview.setOnListViewBaseItemClickListener(new OnListViewBaseItemClickListener() {
			
			@Override
			public void onListViewItemClick(AdapterView<?> parent, View view,int position, long id) {
				((DialogShowerActivityBase) getActivity()).createDialogFragment(new LoginPasswordDialogFragment(personalInfoArray.get(position), intent), "LOGIN_PASSWORD_DIALOG");
			}
		});

		ApplicationInfo.setResponseListener(this);

		this.personalInfoArray = new ArrayList<PersonalDataForm>();
		this.personalListAdapter = new PersonalListAdapter(getActivity(),R.layout.personal_list_item, personalInfoArray);
		
		this.intent = new Intent(this.getActivity(), LeftMenuActivity.class);

		this.personalListview.setAdapter(personalListAdapter);

		this.myRunnable = new Runnable() {
			public void run() {
				personalListAdapter.notifyDataSetChanged();
			}
		};

		this.roundedProgressDialogBase=new RoundedProgressDialogBase();

		return this.vi;
	}

	/**
	 * Bu metod içerisinde öncelikle bir personel listesi update'inin olup
	 * olmadığı kontrol edilir. Eğer bir update gelmişse sunucuya yeniden
	 * personel listesi request'i gönderilir ve yeni liste alınır. Eğer bir
	 * update yoksa splashfragment tarafından elde edilen personel listesi
	 * kullanılır.
	 */
	public void onResume() {
		super.onResume();

		ApplicationInfo.setResponseListener(this);
		ApplicationInfo.setConnectionListener(this);
		createRequest();
	}

	private void updateGUI() {

		/*
		 * Bu blmde personellere ait resim bilgileri dosyaya yazılıyor.
		 */
		FileProcess fileProcess = new FileProcess();

		File dirFile = new File(Environment.getExternalStorageDirectory()+ "//STS//personalImage//");

		/**
		 * Burada klasrn var olup olmadıÛı kontrol ediliyor.Yoksa
		 * olußturuluyor.
		 */
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		/**
		 * Burada personel listesine tek tek bakılıyor ve her bir personee ait
		 * resim dosyaya kayıt ediliyor.
		 */
		for (int i = 0; i < this.personalInfoArray.size(); i++) {
			File file = new File(Environment.getExternalStorageDirectory()+ "//STS//personalImage//"+ String.valueOf(this.personalInfoArray.get(i).getPersonelID()) + ".png");
			Bitmap bitmap = this.convertToBitmap(this.personalInfoArray.get(i).getPersonelImage());
			if (bitmap != null) {
				fileProcess.writeImageToFile(bitmap, file);
			}
		}

		myHandler.post(myRunnable);
	}

	/**
	 * Bu metod aÛrıldıÛı zaman suncuya bir personel listesi talebi gnderilir.
	 */
	public void createRequest() {
		//((FragmentActivityBase) getActivity()).showGeneralDialog(this.roundedProgressDialogBase,"LOGIN_PROGRESS_DIALOG");
		
		PersonalListReq personalListReq = new PersonalListReq();
		personalListReq.setType("PersonalListReq");
		personalListReq.setRequestId(UniqueIdCreator.createUniqueID());

		/**
		 * Burada klasr ieriÛindeki png resimlerine bakılır. Png resimleri
		 * personellerin ID'leri ile kayıt edilmißtir. Bu nedenle bu resimlerin
		 * isimlerinden personel ID bilgisi elde edilerek sunucuya gnderilir.
		 */
		ArrayList<Long> hasImagePersonalIdList = new ArrayList<Long>();

		File dirFile = new File(Environment.getExternalStorageDirectory()+ "//STS//personalImage//");

		/**
		 * Burada klasrn var olup olmadıÛı kontrol ediliyor.Yoksa
		 * olußturuluyor.
		 */
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		File[] contentList = FileProcess.getContentlist(new File(Environment.getExternalStorageDirectory() + "//STS//personalImage//"));
		for (int i = 0; i < contentList.length; i++) {
			if (contentList[i].getName().contains(".png")) {
				String contentNameWithoutPng = contentList[i].getName().replace(".png", "");
				hasImagePersonalIdList.add(Long.valueOf(contentNameWithoutPng));
			}
		}
		personalListReq.setHasImagePersonalIdList(hasImagePersonalIdList);

		ApplicationInfo.getRequestListener().jsonRequestCame(JsonConverter.toJsonString(personalListReq));
		Bundle data = new Bundle();
		data.putString("personalListReq",JsonConverter.toJsonString(personalListReq));
	}

	/**
	 * ListAdapter sınıfı parametre olarak aldıÛı layout'u listview ierisine
	 * yerleßtirir. Yine parametre olarak aldıÛı arraylist'in ierik sayısı
	 * kadar listview'da obje olußturulur. Üst sınıftan overwrite edilen getView
	 * metodunda da listenin elemanlarının alacaÛı veriler dzenlenir.
	 * 
	 * @author Okan ERDOÚAN 12 Haz 2014
	 */
	class PersonalListAdapter extends ArrayAdapter<PersonalDataForm> {

		private Context context;
		private int resourceId;
		private ArrayList<PersonalDataForm> arrayList;

		public PersonalListAdapter(Context context, int textViewResourceId,ArrayList<PersonalDataForm> objects) {
			super(context, textViewResourceId, objects);

			this.context = context;
			this.resourceId = textViewResourceId;

			this.arrayList = objects;
		}

		@SuppressLint("NewApi")
		public View getView(int position, View convertView, ViewGroup parent) {

			convertView = LayoutInflater.from(this.context).inflate(this.resourceId, null);

			PersonalDataForm personalDataForm = (PersonalDataForm) arrayList.get(position);
			TextViewBase personalName = (TextViewBase) convertView.findViewById(R.id.personal_name);
			TextViewBase personalTitle = (TextViewBase) convertView.findViewById(R.id.personal_title);
			TextViewBase personalResponsibility = (TextViewBase) convertView.findViewById(R.id.personal_responsibility);
			ImageViewBase personalImage = (ImageViewBase) convertView.findViewById(R.id.personal_image);

			personalName.setText(personalDataForm.getPersonalName() + " "+ personalDataForm.getPersonelSurName());
			personalTitle.setText(personalDataForm.getTitle());
			personalResponsibility.setText(personalDataForm.getResponsibleFloor());
			if (convert(personalDataForm.getPersonelImage()) != null) {
				personalImage.setBackground(convert(personalDataForm.getPersonelImage()));
			} else {
				FileProcess fileProcess = new FileProcess();
				File file = new File(Environment.getExternalStorageDirectory()+ "//STS//personalImage//"+ String.valueOf(personalDataForm.getPersonelID())+ ".png");

				if (file.exists()) {
					Bitmap bitmap = fileProcess.readImageFromFile(file);
					BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
					personalImage.setBackground(bitmapDrawable);
				}

			}
			return convertView;
		}

		public int getCount() {
			return arrayList.size();
		}

		public void notifyDataSetChanged() {
			super.notifyDataSetChanged();
			this.arrayList = personalInfoArray;
		}

		/**
		 * Verilecek olan bir byte dizisinden yine verilecek olan grsel formata
		 * gre ißlenip sz konusu grsel Ûenin elde edilmesini saÛlamak
		 * amacıyla kullanılacak olan uygulamadır.
		 */
		public Drawable convert(byte[] imageByte) {
			if (imageByte != null) {
				ByteArrayInputStream imageStream = new ByteArrayInputStream(imageByte);
				Bitmap personalLogo = BitmapFactory.decodeStream(imageStream);
				return new BitmapDrawable(getResources(), personalLogo);
			}
			return null;
		}
	}

	/**
	 * Parametre olarak resme ait bir byte dizisi alır ve geriye Bitmap trnde
	 * bir resim dnderir.
	 * 
	 * @param imageByte
	 * @return
	 */
	public Bitmap convertToBitmap(byte[] imageByte) {
		if (imageByte != null) {
			ByteArrayInputStream imageStream = new ByteArrayInputStream(imageByte);
			Bitmap personalLogo = BitmapFactory.decodeStream(imageStream);
			return personalLogo;
		}
		return null;
	}

	/**
	 * Sunucudan gelen cevaplar bu metoda dßer. LoginFragment'ın alabildiÛi iki
	 * adet response vardır. Bunlar UpdateResp ve PersonalListResp'dir.
	 * UpdateResp geldiÛi zaman ierisinde parametre olarak bildirilen
	 * updateStrin'e bakılır. Bu string update edilmesi istenen reqeust'i
	 * bildirir. Bu fragment updateString olarak PersonalListReq'in olup
	 * olmadıÛına bakar. EÛer bu request bildirilmißse sunucuya hemen
	 * PersonalListReq gnderilir. Bylece gncellenmiß personel listesi
	 * sunucudan alınmıß olunur.
	 */
	@Override
	public void responseCame(String response) {

		JSONResponse responseObject = (JSONResponse) JsonConverter.fromJsonString(response, JSONResponse.class);

		if (responseObject.getType().equals("UpdateResp")) {
			UpdateResp updateResp = (UpdateResp) JsonConverter.fromJsonString(response, UpdateResp.class);
			if (updateResp != null) {
				if (updateResp.getUpdateString().equals("PersonalListReq")) {
					createRequest();
				}
			}
		}
		if (responseObject.getType().equals("PersonalListResp")) {
			PersonalListResp personalListResp = (PersonalListResp) JsonConverter.fromJsonString(response, PersonalListResp.class);
			if (personalListResp.getPersonalList() != null) {

				/*
				 * Sunucudan gelen personelListesi bilgisi sharedPreferences'a
				 * yazılıyor.
				 */
				((FragmentActivityBase) getActivity()).createSharedPreferencesManager("sharedpreferences",getActivity());
				((FragmentActivityBase) getActivity()).writeToSharedPreferences("personalDataFormList",JsonConverter.toJsonString(personalListResp));

				this.personalInfoArray = personalListResp.getPersonalList();
				updateGUI();
			}
		}

		if ((FragmentActivityBase) getActivity() != null) {
			//((FragmentActivityBase) getActivity()).closeGeneralDialog(this.roundedProgressDialogBase,"LOGIN_PROGRESS_DIALOG");
		}
	}

	@Override
	public void connectionStatusChanged(ConnectionStatus status) {

		System.out.println("LoginFragment bağlantı durumu değişti.");
		if (status.getConnectionStatusInfo().equals(
				ConnectionStatusInfo.CONNECTED)) {
			((FragmentActivityBase) getActivity()).checkActivasion();
		} else if (status.getConnectionStatusInfo().equals(
			ConnectionStatusInfo.CONNECTION_LOST)) {
			if(!TwoButtonDialogFragmentBase.connectionLostDialogShowing){
				((FragmentActivityBase) getActivity()).showGeneralDialog(new TwoButtonDialogFragmentBase(status.getConnectionInfoMessage(),TwoButtonDialogType.CONNECTION_LOST_DIALOG), "GENERAL_TWO_BUTTON_DIALOG");
				Log.i("LoginFragment", "Bağlantı diyalogu kapalı. Bağlantı kopma diyalogu açıldı..");
			}else{
				Log.i("LoginFragment", "Bağlantı diyalogu açık. Bağlantı kopma diyalogu açılmadı..");
			}
		} else if (status.getConnectionStatusInfo().equals(
			ConnectionStatusInfo.SERVER_NOT_FOUND)) {
			if(!TwoButtonDialogFragmentBase.connectionLostDialogShowing){
				((FragmentActivityBase) getActivity()).showGeneralDialog(new TwoButtonDialogFragmentBase(status.getConnectionInfoMessage(),TwoButtonDialogType.CONNECTION_LOST_DIALOG), "GENERAL_TWO_BUTTON_DIALOG");
				Log.i("LoginFragment", "Bağlantı diyalogu kapalı. Sunucu  bulunamadı diyalogu açıldı..");
			}else{
				Log.i("LoginFragment", "Bağlantı diyalogu açık. Sunucu  bulunamadı diyalogu açılmadı..");
			}
		}
	
		
	}

	

}
